home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / c_dates2.arc / C_DATES.C next >
Text File  |  1991-01-10  |  14KB  |  388 lines

  1. /************************************************************************/
  2. /*  (c)  1987 by James N. Seed,  Atlanta, GA  -  all rights reserved.    */
  3. /*                                    */
  4. /*  Permission is hereby granted to freely distribute and use this    */
  5. /*  document for whatever purpose provided that:            */
  6. /*                                    */
  7. /*  A)    this copyright notice, in its entirety, including the author's    */
  8. /*    name (above) is not removed or altered,                */
  9. /*                                    */
  10. /*  B)    it, and/or any or all of the algorithms it contains, is not    */
  11. /*    sold or distributed FOR MONETARY PROFIT without the express    */
  12. /*    written consent of the author and owner of the copyright,    */
  13. /*    James Seed, and                            */
  14. /*                                    */
  15. /*  C)    a one-time compensatory fee of $10 be paid the author in the    */
  16. /*    event that any or all of these algorithms are employed in any    */
  17. /*    product sold for profit.  This fee must be paid PRIOR to    */
  18. /*    distribution of said product, and should be sent to:        */
  19. /*                                    */
  20. /*    James Seed                            */
  21. /*    2752 Twin Brooks Dr., apt #4                    */
  22. /*    Atlanta, GA  30319                        */
  23. /************************************************************************/
  24.  
  25. /************************************************************************/
  26. /*  All of these routines were written entirely in machine independant,    */
  27. /*  compiler independant, standard ( ANSI ) "C" language.        */
  28. /*                                    */
  29. /*  The only exceptions to the machine independance of the source occur    */
  30. /*  in "jtog" and "fulldte", because they assume the usage of the ASCII    */
  31. /*  character set.                            */
  32. /************************************************************************/
  33.  
  34. /************************************************************************/
  35. /*  Notes:  For those of you that don't already know, a "julian" date    */
  36. /*  =====   is simply the number of days that has transpired since    */
  37. /*        some arbitrary point in time.  For these routines, that    */
  38. /*        arbitrary point in time is 01/00/0000, or the 0th day A.D.    */
  39. /*        A "gregorian" date is simply a date expressed in terms of    */
  40. /*        the month, day, and year, which is what we use today.    */
  41. /*                                    */
  42. /*        The name "julian" comes from the creator of the original    */
  43. /*        concept, Julius Caesar, and I think the name "gregorian"    */
  44. /*        comes from Pope Gregory, who sanctified the continued use    */
  45. /*        of the original Pagan concept, although I'm not sure...    */
  46. /*                                    */
  47. /*        All of these routines assume that year 0000 is a leap year.    */
  48. /*                                    */
  49. /*        In the interest of portability, I have not declared any    */
  50. /*        "unsigned long" variable types, because some compilers do    */
  51. /*        not support it.  The "docs in the box" for each routine,    */
  52. /*        however, specify which long integers should be unsigned,    */
  53. /*        so you can go ahead and change the source to reflect this    */
  54. /*        if you like.  It will only make a difference if you are    */
  55. /*        working with HUGE date numbers ( ie: past year 9999 ) or    */
  56. /*        in the ( unlikely? ) event that you erroneously input a    */
  57. /*        negative julian date. ( a definite no no )            */
  58. /************************************************************************/
  59.  
  60. /************************************************************************/
  61. /*                *** gtoj.c ***                */
  62. /*                                    */
  63. /* This function converts a gregorian date, in the ( month, day, year )    */
  64. /* format, into its respective julian, or day number, equivalent.    */
  65. /* ( 1 = 1st day AD )                            */
  66. /*                                    */
  67. /* The legal input values, in their proper order, are:            */
  68. /*                                    */
  69. /*    month   =  1   to    12            ( unsigned int )    */
  70. /*    day     =  1   to    31            ( unsigned int )    */
  71. /*    year    =  0   to  9999            ( unsigned int )    */
  72. /*                                    */
  73. /* The return value of the function is the julian day number        */
  74. /* expressed as    an unsigned long integer.                */
  75. /*                                    */
  76. /************************************************************************/
  77.  
  78. long gtoj( m, d, y )
  79.  
  80. unsigned int m, d, y;
  81.  
  82. {
  83.     y += ( m += 9 ) / 12 + 399;
  84.     m %= 12;
  85.  
  86.     return ( (long)y*365 + y/4 - y/100 + y/400 + (153*m+2)/5 + d - 146037 );
  87. }
  88.  
  89. /************************************************************************/
  90. /*                *** jtog.c ***                */
  91. /*                                    */
  92. /* This function converts a julian day number ( 1 = 1st day AD ), into    */
  93. /* either a gregorian date character string, in any one of the four    */
  94. /* formats described below, or an array of three integers representing    */
  95. /* the month, day, and year, respectively, of the equivalent gregorian    */
  96. /* date.  Storage for the output is provided by the calling routine.    */
  97. /*                                    */
  98. /* The input values, in their proper order, are:            */
  99. /*                                    */
  100. /*  1.  the julian date to be converted,          ( unsigned long )    */
  101. /*                                    */
  102. /*  2.  a pointer to the output array,              ( char * )    */
  103. /*                                    */
  104. /*  3.  the format code ( described below )                */
  105. /*    specifying the desired output format.          ( unsigned int )    */
  106. /*                                    */
  107. /* The format codes are defined as follows:                */
  108. /*                                    */
  109. /*   CODE            - EXPLANATION -                */
  110. /*                                    */
  111. /*     0  -  output array will hold three integers defined as:        */
  112. /*                                    */
  113. /*            array[0] = month    (   mm )        */
  114. /*            array[1] = day        (   dd )        */
  115. /*            array[2] = year        ( yyyy )        */
  116. /*                                    */
  117. /*         If this format option is used, a type cast will have to    */
  118. /*         be performed on the output pointer to convert it to the    */
  119. /*         appropriate pointer type. ( see example below )        */
  120. /*                                    */
  121. /*     1  -  output string will hold a character string in the        */
  122. /*         format "mmddyy"      ( minimum - char string[7] )        */
  123. /*                                    */
  124. /*     2  -  output string will hold a character string in the        */
  125. /*         format "mmddyyyy"      ( minimum - char string[9] )        */
  126. /*                                    */
  127. /*     3  -  output string will hold a character string in the        */
  128. /*         format "mm/dd/yy"      ( minimum - char string[9] )        */
  129. /*                                    */
  130. /*     4  -  output string will hold a character string in the        */
  131. /*         format "mm/dd/yyyy"  ( minimum - char string[11] )        */
  132. /*                                    */
  133. /*   NOTE -  input of any format code not listed above will be        */
  134. /*         interpreted as code 0.                    */
  135. /*                                    */
  136. /*   The function returns a character pointer to the output array.    */
  137. /*    ______________________________________________________________    */
  138. /*   |           *** example of integer array output ***        |    */
  139. /*   |                                    |    */
  140. /*   |  int    month, dte_array[3];                    |    */
  141. /*   |  long    julian = 548784;                    |    */
  142. /*   |                                    |    */
  143. /*   |  month = ( (int *)jtog( julian, (char *)dte_array, 0 ) )[0]; |    */
  144. /*   |______________________________________________________________|    */
  145. /*                                    */
  146. /*   WARNING -  the output array pointed to must be dimensioned        */
  147. /*        accordingly or a memory overwrite will occur.        */
  148. /************************************************************************/
  149.  
  150. char *jtog( julian, date, fmt )
  151.  
  152. long julian;
  153. char *date;
  154. unsigned int fmt;
  155.  
  156. {
  157.     int  month, day, year, i;
  158.     long numdte, indx = !( fmt & 1 ) * 9900 + 100;
  159.  
  160.     year    = ( julian += 146037 ) * 400 / 146097;
  161.     julian -= (long)year*365 + year/4 - year/100 + year/400;
  162.     year   += julian / ( i = 366 - !!( ( year + 1 ) % 4 ) );
  163.  
  164.     if ( !( julian %= i ) ) julian = 365 + !( year % 4 ), --year;
  165.  
  166.     year += ( month = ( day = (int)julian * 5 - 3 ) / 153 + 2 ) / 12 - 400;
  167.     month = month % 12 + 1;
  168.     day   = day % 153 / 5 + 1;
  169.  
  170.     if ( fmt && fmt < 5 )
  171.     {
  172.          numdte = (long)month * 100 * indx + day * indx + year % indx;
  173.          for ( indx *= 10000, i = 0; indx > 1; ++i )
  174.            date[i] = ( fmt > 2 && ( i == 2 || i == 5 ) )  ?  '/'
  175.                : (char)( numdte / ( indx /= 10 ) % 10 + 48 );
  176.          date[i] = '\0';
  177.     }
  178.     else
  179.     {
  180.          ((int *)date)[0] = month;
  181.          ((int *)date)[1] = day;
  182.          ((int *)date)[2] = year;
  183.     }
  184.  
  185.     return( date );
  186. }
  187.  
  188. /************************************************************************/
  189. /*                *** dow.c ***                */
  190. /*                                    */
  191. /* This function returns the numerical day-of-week of a julian        */
  192. /* date, input as an unsigned long integer.                */
  193. /*                                    */
  194. /* The return value of the function is the day of the week expressed    */
  195. /* as an unsigned integer value, and is enumerated as follows:        */
  196. /*                                    */
  197. /*    Sunday    -  0                            */
  198. /*    Monday    -  1            Thursday  -  4            */
  199. /*    Tuesday   -  2            Friday    -  5            */
  200. /*    Wednesday -  3            Saturday  -  6            */
  201. /*                                    */
  202. /************************************************************************/
  203.  
  204. int dow( julian )
  205.  
  206. long julian;
  207.  
  208. {
  209.     return( (int)( ( julian + 5 ) % 7 ) );
  210. }
  211.  
  212. /************************************************************************/
  213. /*                *** fulldte.c ***            */
  214. /*                                    */
  215. /* This function converts a julian day number ( 1 = 1st day AD ),    */
  216. /* into an equivalent gregorian date descriptive phraze of the form:    */
  217. /*                                    */
  218. /*    "Wednesday September 16, 1987"        ( example )        */
  219. /*                                    */
  220. /* The input values, in their proper order, are:            */
  221. /*                                    */
  222. /*  1.  the julian date to be converted              ( unsigned long )    */
  223. /*                                    */
  224. /*  2.  a pointer to the output character string.     ( char * )    */
  225. /*                                    */
  226. /* The length, in ASCII characters, of the output string is returned    */
  227. /* by the function upon completion, expressed as an unsigned integer.    */
  228. /*                                    */
  229. /* WARNING - the character string pointed to must be dimensioned to    */
  230. /*         at least 29 characters, or a memory overwrite may occur.    */
  231. /*                                    */
  232. /************************************************************************/
  233.  
  234. int fulldte( julian, dtestr )
  235.  
  236. long julian;
  237. char *dtestr;
  238.  
  239. {
  240.     static char *daynme[7]  =  {  "Sunday",    "Monday",   "Tuesday",
  241.                       "Wednesday", "Thursday", "Friday",
  242.                       "Saturday"              };
  243.     static char *mosnme[12] =  {  "January", "February", "March",
  244.                       "April",   "May",      "June",
  245.                       "July",    "August",   "September",
  246.                       "October", "November", "December"   };
  247.  
  248.     static char **text[2] = { daynme, mosnme };
  249.  
  250.     int i, j, k, strt, dtearr[4];
  251.  
  252.     dtearr[0] = dow( julian );
  253.     jtog( julian, (char *)&dtearr[1], 0 );
  254.     --dtearr[1];
  255.  
  256.     for ( i = j = k = 0; i < 2; k = 0, ++i )
  257.     {
  258.           while ( text[i][dtearr[i]][k] )
  259.               dtestr[j++] = text[i][dtearr[i]][k++];
  260.           dtestr[j++] = ' ';
  261.     }
  262.  
  263.     for ( strt = 0, i = 2; i < 4; ++i )
  264.     {
  265.           for ( k = 1000; k; dtearr[i] %= k, k /= 10 )
  266.           {
  267.             if ( strt = strt || dtearr[i] / k )
  268.              dtestr[j++] = (char)( dtearr[i] / k + 48 );
  269.           }
  270.  
  271.           if ( i == 2 ) dtestr[j++] = ',';
  272.  
  273.           dtestr[j++] = ' ';
  274.     }
  275.  
  276.     dtestr[--j] = '\0';
  277.  
  278.     return( j );
  279. }
  280.  
  281. /************************************************************************/
  282. /*                *** daycnt.c ***            */
  283. /*                                    */
  284. /* This function returns the number of days of the specified type that    */
  285. /* exist between the two julian dates input, expressed as an signed    */
  286. /* long integer.                            */
  287. /*                                    */
  288. /* The input values to the function, in their proper order, are:    */
  289. /*                                    */
  290. /*  1.  the beginning julian date              ( unsigned long )    */
  291. /*                                    */
  292. /*  2.  the ending julian date                  ( unsigned long )    */
  293. /*                                    */
  294. /*  3.  the numerical code representing the type            */
  295. /*    of days    to be counted ( described below )     ( unsigned int )    */
  296. /*                                    */
  297. /* The following is a list of the codes used to define the        */
  298. /* type of days that are to be counted:                    */
  299. /*                                    */
  300. /*   CODE        - EXPLANATION -                    */
  301. /*                                    */
  302. /*     0  -  all days                            */
  303. /*                                    */
  304. /*     1  -  all days excluding Sundays                    */
  305. /*                                    */
  306. /*     2  -  all days excluding weekends ( Saturdays and Sundays )    */
  307. /*                                    */
  308. /*   NOTE -  input of any code not listed above will be            */
  309. /*         interpreted as code 0.                    */
  310. /*                                    */
  311. /************************************************************************/
  312.  
  313. long daycnt( juldt1, juldt2, excl )
  314.  
  315. long juldt1, juldt2;
  316. unsigned int excl;
  317.  
  318. {
  319.     int  eff = 7 - ( excl = excl > 2 ? 0 : excl );
  320.  
  321.     if ( !excl-- ) return( juldt2 - juldt1 );
  322.  
  323.     if ( juldt1 > juldt2 ) return( -daycnt( juldt2, juldt1, ++excl ) );
  324.     else
  325.     {
  326.          juldt1 -= !dow( juldt1 ) + ( excl && !( dow( juldt1 ) % 6 ) );
  327.          juldt2 -= !dow( juldt2 ) + ( excl && !( dow( juldt2 ) % 6 ) );
  328.     }
  329.  
  330.     return( ( juldt2 - juldt1 ) / 7 * eff +
  331.         ( dow( juldt2 ) - dow( juldt1 ) + eff ) % eff );
  332. }
  333.  
  334. /************************************************************************/
  335. /*                *** newdate.c ***            */
  336. /*                                    */
  337. /* This function returns a new julian date, expressed as an unsigned    */
  338. /* long integer, arrived at by adding a    specified number of days of a    */
  339. /* specified type to the starting julian date input.            */
  340. /*                                    */
  341. /* In short, it adds days to a date to get a new date.            */
  342. /*                                    */
  343. /* The input values to the function, in their proper order, are:    */
  344. /*                                    */
  345. /*  1.  the beginning julian date              ( unsigned long )    */
  346. /*                                    */
  347. /*  2.  the number of days to be added              ( signed   long )    */
  348. /*                                    */
  349. /*  3.  the numerical code representing the type            */
  350. /*    of days    to be added ( described below )          ( unsigned int )    */
  351. /*                                    */
  352. /* The following is a list of the codes used to define the        */
  353. /* type of days that are to be added to the start date:            */
  354. /*                                    */
  355. /*   CODE        - EXPLANATION -                    */
  356. /*                                    */
  357. /*     0  -  weekdays and weekends (all days)                */
  358. /*                                    */
  359. /*     1  -  weekdays and Saturdays only (Sundays skipped over)        */
  360. /*                                    */
  361. /*     2  -  weekdays only (weekends skipped over)            */
  362. /*                                    */
  363. /*   NOTE -  input of any code not listed above will be            */
  364. /*         interpreted as code 0.                    */
  365. /*                                    */
  366. /************************************************************************/
  367.  
  368. long newdate( juldte, days, incl )
  369.  
  370. long juldte, days;
  371. unsigned int incl;
  372.  
  373. {
  374.     int eff = 7 - ( incl = incl > 2 ? 0 : incl ), rvrse = 0;
  375.  
  376.     if ( !incl-- ) return( juldte + days );
  377.  
  378.     if ( days < 0 )
  379.     {
  380.          rvrse   = eff + 1;
  381.          juldte += !dow( juldte ) + 2 * ( incl && !( 6 - dow( juldte ) ) );
  382.     }
  383.     else juldte -= !dow( juldte ) + ( incl && !( dow( juldte ) % 6 ) );
  384.  
  385.     return( juldte + days / eff * 7 + days % eff + ++incl *
  386.           ( ( dow( juldte ) + days % eff - rvrse ) / ( eff + 1 ) ) );
  387. }
  388.